home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / AmigaUUCP / dnews / refs.c < prev    next >
C/C++ Source or Header  |  1991-02-02  |  6KB  |  386 lines

  1.  
  2. /*
  3.  *  REFS.C
  4.  *
  5.  *  Handles the References: line
  6.  */
  7.  
  8. #include "defs.h"
  9.  
  10. /*
  11.  *  hash table for killed references
  12.  */
  13.  
  14. #define HSIZE    256
  15. #define HMASK    (HSIZE-1)
  16.  
  17. Prototype void AddKillFile(char *, int, int);
  18. Prototype void RemKillFile(char *);
  19. Prototype void LoadKillFile(char *);
  20. Prototype void SaveKillFile(char *);
  21.  
  22. Prototype char *ReferenceLineOf(NGroup *, int);
  23. Prototype char *NewsMessageIdOf(NGroup *, int);
  24. Prototype char *SubjectOf(NGroup *, int, int);
  25. Prototype char *StripRE(char *);
  26. Prototype int FindArticleReferencing(NGroup *, char *, int);
  27. Prototype int ArticleRefNotKilled(NGroup *, char *, int);
  28. Prototype char *NextRef(char **);
  29.  
  30. /*
  31.  *  Hash table for references
  32.  */
  33.  
  34. typedef struct Hash {
  35.     struct  Hash *Next;
  36.     time_t  TTerm;    /*  terminate entry after time tterm    */
  37.     char    Id[4];
  38. } Hash;
  39.  
  40. Local Hash **FindRefHash(char *);
  41. Local void AddRefHash(Hash **, char *, time_t);
  42. Local int hash(char *);
  43.  
  44. static Hash *Table[HSIZE];
  45.  
  46. /*
  47.  *  Add References: field to kill file.  Kill file entry will exist for 30
  48.  *  days.
  49.  */
  50.  
  51. void
  52. AddKillFile(refs, days, noBrkUp)
  53. char *refs;
  54. int days;
  55. int noBrkUp;
  56. {
  57.     char *id;
  58.     Hash **ph;
  59.     Hash *h;
  60.  
  61.     if (days)
  62.     days = time(0) + days * 1440 * 60;  /*  seconds  */
  63.  
  64.     if (noBrkUp) {
  65.     ph = FindRefHash(refs);
  66.     if (h = *ph) {
  67.         h->TTerm = days;
  68.     } else {
  69.         AddRefHash(ph, refs, days);
  70.     }
  71.     } else {
  72.     while (id = NextRef(&refs)) {
  73.         ph = FindRefHash(id);
  74.         if (h = *ph) {
  75.         h->TTerm = days;    /*  now seconds */
  76.         } else {
  77.         AddRefHash(ph, id, days);
  78.         }
  79.     }
  80.     }
  81. }
  82.  
  83. void
  84. RemKillFile(refs)
  85. char *refs;
  86. {
  87.     char *id;
  88.     Hash **ph;
  89.     Hash *h;
  90.  
  91.     while (id = NextRef(&refs)) {
  92.     ph = FindRefHash(id);
  93.     if (h = *ph) {
  94.         *ph = h->Next;
  95.         free(h);
  96.     }
  97.     }
  98. }
  99.  
  100. void
  101. LoadKillFile(user)
  102. char *user;
  103. {
  104.     char id[128];
  105.     char buf[64];
  106.     long tterm;
  107.     FILE *fi;
  108.  
  109.     sprintf(buf, "%s.dnewskl", user);
  110.     if (fi = openlib(buf)) {
  111.     while (fgets(TmpBuf, sizeof(TmpBuf), fi)) {
  112.         Hash **ph;
  113.         char *ptr;
  114.         short len;
  115.  
  116.         tterm = strtol(TmpBuf, &ptr, 0);
  117.         while (*ptr == ' ' || *ptr == '\t')
  118.         ++ptr;
  119.         strncpy(id, ptr, sizeof(id) - 1);
  120.         id[sizeof(id)-1] = 0;
  121.         len = strlen(id);
  122.         if (len && id[len-1] == '\n')
  123.         id[--len] = 0;
  124.  
  125.         if (tterm) {
  126.         if (*(ph = FindRefHash(id)) == NULL)
  127.             AddRefHash(ph, id, tterm);
  128.         }
  129.     }
  130.     fclose(fi);
  131.     }
  132. }
  133.  
  134. void
  135. SaveKillFile(user)
  136. char *user;
  137. {
  138.     char buf[64];
  139.     FILE *fo;
  140.     time_t curtime = time(NULL);
  141.  
  142.     sprintf(buf, "%s.dnewskl", user);
  143.     if (fo = openlib_write(buf)) {
  144.     Hash **ph;
  145.     short i;
  146.  
  147.     for (ph = Table, i = 0; i < HSIZE; ++i, ++ph) {
  148.         Hash *h;
  149.         for (h = *ph; h; h = h->Next) {
  150.         if (h->TTerm == -1 || (h->TTerm && h->TTerm > curtime))
  151.             fprintf(fo, "%d %s\n", h->TTerm, h->Id);
  152.         }
  153.     }
  154.     fclose(fo);
  155.     }
  156. }
  157.  
  158. char *
  159. ReferenceLineOf(grp, artno)
  160. NGroup *grp;
  161. int artno;
  162. {
  163.     FILE *fi;
  164.     FNode **pfn = FindFNCache(grp->RefBase, artno);
  165.  
  166.     {
  167.     FNode *fn;
  168.     if (fn = *pfn)
  169.         return(fn->Id);
  170.     }
  171.     {
  172.     if (fi = fopen(FileForArticle(grp, artno), "r")) {
  173.         char *field = FindField(fi, "References:");
  174.         fclose(fi);
  175.         if (field) {
  176.         AddFNCache(pfn, artno, field);
  177.         return(field);
  178.         }
  179.     }
  180.     }
  181.     AddFNCache(pfn, artno, NULL);
  182.     return(NULL);
  183. }
  184.  
  185. char *
  186. SubjectOf(grp, artno, stripre)
  187. NGroup *grp;
  188. int artno;
  189. {
  190.     FILE *fi;
  191.     FNode **pfn = FindFNCache(grp->SubBase, artno);
  192.  
  193.     {
  194.     FNode *fn;
  195.     if (fn = *pfn) {
  196.         if (stripre)
  197.         return(StripRE(fn->Id));
  198.         return(fn->Id);
  199.     }
  200.     }
  201.     {
  202.     if (fi = fopen(FileForArticle(grp, artno), "r")) {
  203.         char *field = FindField(fi, "Subject:");
  204.         fclose(fi);
  205.         if (field) {
  206.         AddFNCache(pfn, artno, field);
  207.         if (stripre)
  208.             field = StripRE(field);
  209.         return(field);
  210.         }
  211.     }
  212.     }
  213.     AddFNCache(pfn, artno, NULL);
  214.     return(NULL);
  215. }
  216.  
  217.  
  218. char *
  219. NewsMessageIdOf(grp, artno)
  220. NGroup *grp;
  221. int artno;
  222. {
  223.     FILE *fi;
  224.     FNode **pfn = FindFNCache(grp->IdBase, artno);
  225.  
  226.     {
  227.     FNode *fn;
  228.     if (fn = *pfn)
  229.         return(fn->Id);
  230.     }
  231.     {
  232.     if (fi = fopen(FileForArticle(grp, artno), "r")) {
  233.         char *field = FindField(fi, "Message-ID:");
  234.         fclose(fi);
  235.         if (field) {
  236.         AddFNCache(pfn, artno, field);
  237.         return(field);
  238.         }
  239.     }
  240.     }
  241.     AddFNCache(pfn, artno, NULL);
  242.     return(NULL);
  243. }
  244.  
  245.  
  246. /*
  247.  *  Given the msg-id of an article (msgid), find it amoung the References:
  248.  *  line of later articles.
  249.  */
  250.  
  251. int
  252. FindArticleReferencing(grp, msgid, artno)
  253. NGroup *grp;
  254. char *msgid;
  255. int artno;
  256. {
  257.     char *field = ReferenceLineOf(grp, artno);
  258.     char *id;
  259.  
  260.     if (field == NULL)
  261.     return(0);
  262.     while (id = NextRef(&field)) {
  263.     /*printf("COMPARE: %s vs %s artno %d\n", msgid, id, artno);*/
  264.     if (strcmp(msgid, id) == 0)
  265.         break;
  266.     }
  267.     if (id)
  268.     return(1);
  269.     return(0);
  270. }
  271.  
  272. /*
  273.  *  Is the specified article (grp, artno) in the kill list ?  That is, if
  274.  *  any of the fields in the article's References: line are on the kill list
  275.  *  we return TRUE.
  276.  */
  277.  
  278. int
  279. ArticleRefKilled(grp, artno)
  280. NGroup *grp;
  281. int artno;
  282. {
  283.     char *refs;
  284.     char *id;
  285.     Hash **ph;
  286.  
  287.     if (refs = ReferenceLineOf(grp, artno)) {
  288.     while (id = NextRef(&refs)) {
  289.         if (*(ph = FindRefHash(id))) {
  290.         return(1);
  291.         }
  292.     }
  293.     }
  294.     if (refs = SubjectOf(grp, artno, 1)) {
  295.     if (*(ph = FindRefHash(refs))) {
  296.         return(1);
  297.     }
  298.     }
  299.     return(0);
  300. }
  301.  
  302.  
  303. char *
  304. NextRef(ppt)
  305. char **ppt;
  306. {
  307.     char *ptr = *ppt;
  308.     char *base;
  309.     static char buf[256];
  310.  
  311.     while (*ptr == ' ' || *ptr == 9 || *ptr == '\n')
  312.     ++ptr;
  313.     base = buf;
  314.     while (*ptr && *ptr != ' ' && *ptr != 9 && *ptr != '\n')
  315.     *base++ = *ptr++;
  316.     *base = 0;
  317.     *ppt = ptr;
  318.     if (base == buf)
  319.     return(NULL);
  320.     return(buf);
  321. }
  322.  
  323. /*
  324.  *                HASH TABLE ROUTINES
  325.  */
  326.  
  327. Hash **
  328. FindRefHash(id)
  329. char *id;
  330. {
  331.     Hash **ph = Table + hash(id);
  332.     Hash *h;
  333.  
  334.     while (h = *ph) {
  335.     if (strcmp(id, h->Id) == 0)
  336.         break;
  337.     ph = &h->Next;
  338.     }
  339.     return(ph);
  340. }
  341.  
  342. Local
  343. void
  344. AddRefHash(ph, id, ti)
  345. Hash **ph;
  346. char *id;
  347. time_t ti;
  348. {
  349.     Hash *h = malloc(sizeof(Hash) - sizeof(h->Id) + strlen(id) + 1);
  350.  
  351.     strcpy(h->Id, id);
  352.     h->TTerm = ti;
  353.     h->Next = *ph;
  354.     *ph = h;
  355. }
  356.  
  357. int
  358. hash(ptr)
  359. char *ptr;
  360. {
  361.     long hv = 0x1234ADC3;
  362.  
  363.     while (*ptr) {
  364.     hv = (hv >> 23) ^ (hv << 5) ^ *ptr;
  365.     ++ptr;
  366.     }
  367.     return(hv & HMASK);
  368. }
  369.  
  370. char *
  371. StripRE(str)
  372. char *str;
  373. {
  374.     for (;;) {
  375.     while (*str == ' ' || *str == '\t')
  376.         ++str;
  377.     if (strnicmp(str, "re:", 3) == 0) {
  378.         str += 3;
  379.         continue;
  380.     }
  381.     break;
  382.     }
  383.     return(str);
  384. }
  385.  
  386.